package com.kly.ai.controller;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.kly.ai.app.LoveApp;
import com.kly.ai.app.MyAgent;
import com.kly.ai.chatmemory.FileBasedChatMemory;
import com.kly.ai.common.BaseResponse;
import com.kly.ai.common.ResultUtils;
import com.kly.ai.manus.OpenManus;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.tool.ToolCallback;
import org.springframework.http.MediaType;
import org.springframework.http.codec.ServerSentEvent;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import reactor.core.publisher.Flux;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;

import static com.kly.ai.constants.FileConstant.MESSAGE_SAVE_DIR;

/**
 * @author admin
 * @date 2025/5/30
 */
@RestController
@RequestMapping("/ais")
@Slf4j
public class AIController {

    @Resource
    private LoveApp loveApp;

    @Resource
    private ToolCallback[] allTools;

    @Resource
    private ChatModel dashscopeChatModel;

    @Resource
    private OpenManus openManus;

    @Resource
    private MyAgent myAgent;


    /**
     * 同步对话
     */
    @GetMapping("/sync")
    public String chatBySync(String conversionId, String question) {
        String msg = loveApp.callByCommon(conversionId, question);
        return msg;
    }


    /**
     * 异步消息 mediaType
     */
    @GetMapping(value = "/sse1", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<String> chatBySSE1(String conversionId, String question) {

        return loveApp.callByCommonFlux(conversionId, question);
    }

    /**
     * 异步消息 ServerSentEvent
     */
    @GetMapping("/sse2")
    public Flux<ServerSentEvent<String>> chatBySSE2(String conversionId, String question) {

        return loveApp.callByCommonFlux(conversionId, question).map(chunk -> ServerSentEvent.<String>builder().data(chunk).build());
    }

    /**
     * 异步消息 SseEmitter
     */
    @GetMapping("/sse3")
    public SseEmitter chatBySSE3(String conversionId, String question) {
        SseEmitter sseEmitter = new SseEmitter(600000L);
        loveApp.callByCommonFlux(conversionId, question)
                .subscribe(
                        chunk -> {
                            try {
                                sseEmitter.send(chunk);
                            } catch (IOException e) {
                                log.error("error in " + e.getMessage());
                                sseEmitter.completeWithError(e);
                            }
                        },
                        sseEmitter::completeWithError,
                        sseEmitter::complete
                );
        return sseEmitter;
    }


    @GetMapping("/manus")
    public SseEmitter chatByManus(String question) {
        return openManus.runStream(question, "123");
    }



    /**
     * 获取消息列表
     */
    @GetMapping("/messages")
    public BaseResponse<List<Message>> getMessages(String conversationId, Integer current, Integer size) {
        FileBasedChatMemory fileBasedChatMemory = new FileBasedChatMemory(MESSAGE_SAVE_DIR);
        //     默认展示10条消息
        int start = (current - 1) * size;
        List<Message> messages = fileBasedChatMemory.listMessages(conversationId, start, start + size);
        return ResultUtils.success(messages);
    }


    /**
     * 查询会话记录
     */
    @GetMapping("/conversations")
    public BaseResponse<List<String>> getConversation() {
        // 获取文件下所有文件
        List<String> conversations = new ArrayList<>();
        List<String> fileNames = FileUtil.listFileNames(MESSAGE_SAVE_DIR);
        fileNames.forEach(fileName -> {
            if (StrUtil.isNotBlank(fileName)) {
                // 截取文件名
                fileName = fileName.substring(0, fileName.lastIndexOf("."));
                conversations.add(fileName);
            }
        });

        // 默认20个会话
        return ResultUtils.success(conversations);
    }

    /**
     * 新建会话
     */
    @PostMapping("/conversations")
    public BaseResponse<Long> newConversation() {
        // 雪花算法生成id
        long snowflakeNextId = IdUtil.getSnowflakeNextId();
        return ResultUtils.success(snowflakeNextId);
    }


    /**
     * 删除会话
     */
    @DeleteMapping("/conversations")
    public BaseResponse<String> deleteConversation(String conversationId) {
        File file = new File(MESSAGE_SAVE_DIR + "/" + conversationId + ".kryo");
        if (FileUtil.exist(file)) {
            FileUtil.del(file);
        }
        return ResultUtils.success("ok");
    }


    @GetMapping("/call")
    public SseEmitter call(String conversionId, String question) {
        // 判断id是否为空 为空则创建
        SseEmitter sseEmitter = new SseEmitter(600000L);
        CompletableFuture.runAsync(() -> {
            loveApp.callByCommonFlux(conversionId, question)
                    .subscribe(
                            chunk -> {
                                try {
                                    sseEmitter.send(chunk);
                                } catch (IOException e) {
                                    log.error("error in " + e.getMessage());
                                    sseEmitter.completeWithError(e);
                                }
                            },
                            sseEmitter::completeWithError,
                            sseEmitter::complete
                    );
        });
        return sseEmitter;
    }

    @GetMapping("/call/love")
    public SseEmitter callLove(String conversationId, String question) {
        SseEmitter sseEmitter = new SseEmitter(600000L);
        CompletableFuture.runAsync(() -> {
            loveApp.call(conversationId, question)
                    .subscribe(
                            chunk -> {
                                try {
                                    sseEmitter.send(chunk);
                                } catch (IOException e) {
                                    log.error("error in " + e.getMessage());
                                    sseEmitter.completeWithError(e);
                                }
                            },
                            sseEmitter::completeWithError,
                            sseEmitter::complete
                    );
        });
        return sseEmitter;
    }

    /**
     * agent my对话
     */
    @GetMapping("/call/psychologist")
    public SseEmitter callByPsychologist(String conversationId, String question) {
        SseEmitter sseEmitter = new SseEmitter(600000L);
        myAgent.call(conversationId, question)
                .subscribe(
                        chunk -> {
                            try {
                                sseEmitter.send(chunk);
                            } catch (IOException e) {
                                log.error("error in " + e.getMessage());
                                sseEmitter.completeWithError(e);
                            }
                        },
                        sseEmitter::completeWithError,
                        sseEmitter::complete
                );
        return sseEmitter;
    }



}
